﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ComunesMGI.DataTypes;
using ComunesMGI.Enum;
using ComunesMGI.Constantes;


using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.IO;


namespace MGI.AccesoDatos
{
    class SharepointProxy: ISharepoint
    {

        #region ISharepoint Members

        /// <summary>
        /// Dado los títulos de los campos y otra información traida del xml 
        /// de configuración, se retorna una lista con información mas completa 
        /// (incluyendo la anterior) acerca de los campos, traida del sitio 
        /// sharepoint indicado por cliente-sistema.
        /// </summary>
        /// <param name="cliente"></param>
        /// <param name="sistema"></param>
        /// <param name="tipoLista"></param>
        /// <param name="nomCampos"></param>
        /// <returns>List<DataCampo></returns>
        public List<DataCampo> getCampos(DataCliente cliente, DataSistema sistema,Lista tipoLista,List<DataCampo> nomCampos)
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            
            SPList spLista;
            switch (tipoLista)
            {
                case Lista.Incidentes:
                    spLista = myWeb.Lists["Incidentes"];
                    break;
                case Lista.Tareas:
                    spLista = myWeb.Lists["Tareas"];
                    break;
                default:
                    spLista = myWeb.Lists["Incidentes"];
                    break;
            }
            List<DataCampo> campos = new List<DataCampo>();
            foreach (DataCampo dataCampo in nomCampos)
            {
                SPField spField = spLista.Fields[dataCampo.Titulo];
                CampoSharepoint tipoCampo = spTypeToCampoSharepoint(spField.TypeAsString);
                string tituloCampo =    spField.Title;
                string internalCampo =  spField.InternalName;
                int largoCampo =        System.Convert.ToInt32(spField.DisplaySize);
                bool requeridoCampo =   spField.Required;
                string defaultCampo =   spField.DefaultValue;
                
                DataCampo dataCampo2 = new DataCampo(tipoCampo,tituloCampo,defaultCampo,requeridoCampo, null);
                dataCampo2.ParteMail = dataCampo.ParteMail;
                
                switch (tipoCampo)
                {
                    case CampoSharepoint.Choice :
                        List<string> cadaChoice = new List<string>();
                        foreach (string choice in ((SPFieldChoice)spField).Choices )
                        {
                            cadaChoice.Add(choice);
                        }
                        dataCampo2.Opciones = cadaChoice;
                        break;
                    default:
                        break;
                }
                campos.Add(dataCampo2);        
            }
            return campos;            
        }


    








        /// <summary>
        /// Alta de incidente en sharepoint
        /// </summary>
        /// <param name="sistema"></param>
        public DataAltaIncidente addIncidente(DataSistema sistema, List <DataAttachment> archivos) 
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Incidentes"];
            DataAltaIncidente altaIncidente = Impactar(myWeb, spLista, sistema.Campos, archivos);
            myWeb.Close();
            mySite.Close();
            return altaIncidente;

        }


       

        /// <summary>
        /// Retorna información de todos los incidentes en el sitio 
        /// del cliente-sistema
        /// </summary>
        /// <param name="cliente"></param>
        /// <param name="sistema"></param>
        /// <returns>List<DataIncidente></returns>
        public List<DataIncidente> getIncidentes(DataSistema sistema) 
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Incidentes"];
            List<DataIncidente> listaDataIncidente = new List<DataIncidente> (); 
            string tituloIncidente;
            string idIncidente;
            foreach (SPListItem spItem in spLista.Items) 
            {
                idIncidente  =  spItem["ID"].ToString();
                if (spItem["Título"] != null)
                {
                    tituloIncidente = spItem["Título"].ToString();
                }
                else 
                {
                    tituloIncidente = "-no hay dato-";
                }
                DataIncidente dataIncidente = new DataIncidente(idIncidente, tituloIncidente);
                listaDataIncidente.Add(dataIncidente);
            }
            myWeb.Close();
            mySite.Close();
            return listaDataIncidente;
        }

        /// <summary>
        /// Retorna información de todos los incidentes en el sitio 
        /// del cliente-sistema
        /// </summary>
        /// <param name="cliente"></param>
        /// <param name="sistema"></param>
        /// <returns>List<DataIncidente></returns>
        public List<DataIncidenteReporte> getIncidentesReporte(DataSistema sistema)
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Incidentes"];
            List<DataIncidenteReporte> listaDataIncidente = new List<DataIncidenteReporte>();
            string titulo = null;
            string url = null;
            string responsable = null;
            string nomSistema = null;
            string wp = null;
            string descripcion = null;
            string idIncidente = null;
            DateTime fechaPropuesto = ConstantesMGI.FechaVacia;
            DateTime fechaCierre = ConstantesMGI.FechaVacia;


            url = spLista.DefaultViewUrl;
            foreach (SPListItem spItem in spLista.Items)
            {
                idIncidente = spItem["ID"].ToString();
                titulo = spItem["Título"].ToString();
                url = url + "?ID=" + idIncidente;
                responsable = "NO LO TENEMOS TODAVIA";
                nomSistema = sistema.Nombre;
                if (spItem["WP"] != null) 
                {
                    wp = spItem["WP"].ToString();
                }
                if (spItem["Descripción"] != null)
                {
                    descripcion = spItem["Descripción"].ToString();
                }
                if (spItem["Fecha Propuesto"] != null)
                {
                    fechaPropuesto = (DateTime)spItem["Fecha Propuesto"];
                }
                if (spItem["Fecha Cierre"] != null)
                {
                    fechaCierre = (DateTime)spItem["Fecha Cierre"];
                }

                DataIncidenteReporte dataIncidente = new DataIncidenteReporte(idIncidente,titulo,url,responsable,nomSistema,wp,descripcion,fechaPropuesto,fechaCierre);
                listaDataIncidente.Add(dataIncidente);
            }
            myWeb.Close();
            mySite.Close();
            return listaDataIncidente;
        }

        public List<DataIncidente> getIncidentesWP(DataSistema sistema, DataWP workPackage) 
        {

            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Incidentes"];
            List<DataIncidente> listaDataIncidente = new List<DataIncidente>();
            string tituloIncidente;
            string idIncidente;
            foreach (SPListItem spItem in spLista.Items)
            {
                if (spItem["WP"] != null)
                {
                    string textoWP = spItem["WP"].ToString();
                    if (workPackage.Id == System.Convert.ToInt32(textoWP))
                    {
                        idIncidente = spItem["ID"].ToString();
                        if (spItem["Título"] != null)
                        {
                            tituloIncidente = spItem["Título"].ToString();
                        }
                        else
                        {
                            tituloIncidente = "-no hay dato-";
                        }
                        DataIncidente dataIncidente = new DataIncidente(idIncidente, tituloIncidente);
                        listaDataIncidente.Add(dataIncidente);
                    }
                }
            }
            myWeb.Close();
            mySite.Close();
            return listaDataIncidente;
        }






        /// <summary>
        /// Retorna las tareas en el sitio del sistema y cliente indicados 
        /// que esten asociadas al incidente indicado
        /// </summary>
        /// <param name="cliente"></param>
        /// <param name="sistema"></param>
        /// <param name="incidente"></param>
        /// <returns>List<DataTarea></returns>
        public List<DataTarea> getTareas (DataCliente cliente, DataSistema sistema, DataIncidente incidente)
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Tareas"];
            List<DataTarea> listaDataTarea  = new List<DataTarea>();
            foreach (SPListItem spItem in spLista.Items)
            {
                if (spItem["IDOriginal"].ToString() == incidente.IdIncidente)
                {
                    DataTarea dataTarea = new DataTarea(spItem["ID"].ToString(), spItem["Título"].ToString());
                    listaDataTarea.Add(dataTarea);
                }
            }
            myWeb.Close();
            mySite.Close();
            return listaDataTarea;
        }

        /// <summary>
        /// Dado un incidente de determinado sistema, una tarea y un usuario,
        /// se asigna la tarea al usuario y se asocia la misma al incidente.
        /// 
        /// </summary>
        /// <param name="sistema"></param>
        /// <param name="incidente"></param>
        /// <param name="tarea"></param>
        /// <param name="usuario"></param>
        /// <returns>string conteniendo la dirección de email del usuario al que se le quiere asignar la tarea
        /// o si no es válido el mismo, se retorna null</returns>
        public string asignarResponsable(DataSistema sistema, DataIncidente incidente, DataTarea tarea, DataUsuario usuario)
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Tareas"];
            SPListItem spItem = spLista.Items.GetItemById(System.Convert.ToInt32(tarea.IdTarea));

            string mail = null;
            if (SPUtility.IsLoginValid(mySite, usuario.Nombre ))
            {
                SPUser spUser = myWeb.AllUsers[usuario.Nombre];
                spItem["Asignado a"] = spUser;
                spItem["IDOriginal"] = incidente.IdIncidente;
                spItem.Update();
                mail = spUser.Email;            
            }

            myWeb.Close();
            mySite.Close();
            return mail;
            
        }

        public void setIncidenteWP(DataCliente cliente, DataSistema sistema, DataWP workPackage, DataIncidente dataIncidente)
        {
            SPSite mySite = new SPSite(sistema.Sitio);
            SPWeb myWeb = mySite.OpenWeb();
            SPList spLista = myWeb.Lists["Incidentes"];
            SPListItem spItem = spLista.Items.GetItemById(System.Convert.ToInt32(dataIncidente.IdIncidente));
            spItem["WP"] = workPackage.Id;
            spItem.Update();
            
            myWeb.Close();
            mySite.Close();
            
        }

        public bool adjuntarArchivoIncidente(string nombreArchivo, DataSistema sistema, DataIncidente incidente, string nroTemp) 
        {
            try
            {
                string uploadFolder = @".\";
                string filename = "Upload" + nroTemp + ".tmp";
                string filePath = Path.Combine(uploadFolder, filename);
                FileInfo archivo = new FileInfo(filePath);

                if (archivo.Exists)
                {
                    byte[] contenido = File.ReadAllBytes(filePath);
                    SPSite mySite = new SPSite(sistema.Sitio);
                    SPWeb myWeb = mySite.OpenWeb();
                    SPList spLista = myWeb.Lists["Incidentes"];
                    SPListItem spItem = spLista.Items.GetItemById(System.Convert.ToInt32(incidente.IdIncidente));
                    spItem.Attachments.AddNow(nombreArchivo, contenido);
                    myWeb.Close();
                    mySite.Close();

                    File.Delete(filePath);
                    return true;
                }
                else
                {
                    //return false;
                    throw new Exception("No hay contenido cargado en el servidor");
                   
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }


        #endregion

        /// <summary>
        /// Dada una lista de sharepoint y una lista de datacampo 
        /// conteniendo nombre de los campos, tipo y un valor para los 
        /// mismos, se realiza el alta en sharepoint con la información. 
        /// Se usa tambien el sitio sharepoint para obtener información sobre
        /// la conversión de fechas del formato "dd-mm-aaaa hh:mm" a
        /// cualquier formato configurado en el sharepoint.
        /// También se pueden adjuntar archivos.
        /// 
        /// Retorna ID y otra información de lo creado.
        /// </summary>
        /// <param name="myWeb"></param>
        /// <param name="spLista"></param>
        /// <param name="campos"></param>
        /// <param name="archivos"></param>
        /// <returns>DataAltaIncidente</returns>
        public DataAltaIncidente Impactar(SPWeb myWeb, SPList spLista, List<DataCampo> campos, List<DataAttachment> archivos)
        {
            



            SPListItem newItem = spLista.Items.Add();
            foreach (DataCampo dataCampo in campos)
            {
                switch (dataCampo.Tipo)
                {
                    case CampoSharepoint.DateTime:
                        string[] fechaHora = dataCampo.Valor.Split(' ');
                        newItem[dataCampo.Titulo] = SPUtility.ParseDate(myWeb, fechaHora[0], fechaHora[1], false);
                        break;
                    default:
                        newItem[dataCampo.Titulo] = dataCampo.Valor;
                        break;
                }
            }
            newItem.Update();
            
            //Se intentan adjuntar los archivos enviados al SPItem 
            if (archivos != null)
            {
                foreach (DataAttachment dataArchivo in archivos)
                {
                    newItem.Attachments.AddNow(dataArchivo.NombreArchivo, dataArchivo.Contenido);
                }
            }
            return new DataAltaIncidente(newItem.ID.ToString(), spLista.DefaultViewUrl);
        }



        /// <summary>
        /// Mapea los tipos de campos de sharepoint a los de MGI
        /// </summary>
        /// <param name="spType">String representando el tipo de datos de sharepoint</param>
        /// <returns></returns>
        public static CampoSharepoint spTypeToCampoSharepoint(string spType)
        {
            switch (spType)
            {
                case "Choice":
                    return CampoSharepoint.Choice;
                case "DateTime":
                    return CampoSharepoint.DateTime;
                case "Number":
                    return CampoSharepoint.Number;
                case "Text":
                    return CampoSharepoint.Text;
                case "Boolean":
                    return CampoSharepoint.Boolean;
                case "Note":
                        return CampoSharepoint.Note;
                default:
                    throw new NotImplementedException();
            }
        }

    }
}
